Git Internals 读书笔记。
Git Object Types
Git有四种对象类型,分别是Blob、Tree、Commit和Tag,都存储在对象数据库里,都是通过Zlib压缩过的,使用SHA-1值(内容的哈希值)来表示。
使用书上的例子:

Blob
在Git中,文件的内容是作为Blob进行存储的。

对于具有相同内容的不同文件,只存储一份。

Tree
Tree就对应着目录。

tree存储该目录下的目录和文件的信息(mode,type,name,sha)。

Commit
commit对象指向一个tree对象,然后额外保存了作者,提交者,提交信息和上次提交这些信息。

第一次提交

第二次提交
在第二次提交中,就有了parent这一信息,指向上一次的提交对象。

Tag
Tag对象指向一个特定的commit对象,保存object,type,tag,tagger和message信息。type一般就是commit,object就是这个commit的SHA-1值。

Git Data Model
The Model

带颜色是不可变对象。
Example
目录文件如下
|-- init.rb
-- lib
| -- base
| -- base_include.rb
-- my_plugin.rb
第一次提交后,Git Model如下

branch指向最近的一次提交,HEAD指向当前的branch。
现在修改lib/base/base_include.rb文件,然后提交,并创建一个tag。
修改了文件,其父目录以及父目录的父目录直到最顶层目录的内容都被修改了,就会产生新的对象。对于没有改变的文件和目录则不会产生新对象。

现在修改init.rb文件,然后提交。
由于只修改了init.rb文件,其他的子目录并没有变化,所以就不会产生其他的新对象。如下图所示。

这样的一种模型,我们可以通过当前的HEAD得到所有的历史文件。
Traversal
当进行checkout的时候,通过查看.git/refs目录下的branch,tag,remote,将当前的working directory的内容切换到指定的commit的内容。

Branching and Merging
在Git中,创建分支,切换分支是非常容易的,就是新建一个文件和写几个字符的事。
在这个例子中,创建一个experiment分支,然后对master和experiment分支分别提交。现在就是下面这个样子。

将experiment分支合并到master分支后就像下面这样。

Remotes
远程分支的名字类似与这样origin/master表示远程仓库origin的master分支。远程仓库的名字origin是可以自定义的,不一定就是origin。
下面表示有三个分支,两个远程仓库分支idea和master,一个本地分支。

对这三个分支进行合并,就成了下面这个样子。

Rebasing
在多人合作开发时,将别人的代码合并到自己本地时,就会产生下面所示的情况。

C2,C4,C5这些并没有什么实质的内容,只是进行合并产生的提交。当有大量的这些提交后,我们的提交历史就会变得不清晰。这时,我们可以使用rebase。
使用rebase的效果和merge的效果如下所示。
1是rebase产生的提交历史。
2是merge产生的提交历史。

rebase只在本地分支上使用,不要在公共的分支上进行rebase!